package pt.isel.pdm.ouryamba;

import android.content.Intent;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

public class StatusActivity extends BaseActivity implements OnClickListener, TextWatcher, IMyListener, Runnable
{

	private Button submit;
	private EditText editText;
	private TextView text;
	public final static String ID = StatusActivity.class.getName();
	private final Integer onSuccessToken = 2;
	private Intent uploadIntent;
	
	
//Own methods

	/**
	 * Enable the clicks on the submit button.
	 * According to the boolean parameter it change the text of the button or not.
	 * 
	 * @param changeText Indicate whether the button text should be changed or not.
	 * */
	private void enableSubmit(boolean changeText) 
	{
		submit.setEnabled(true);
		if(changeText)
		{
			submit.setText(R.string.buttonUpdateFace);
		}
	}
	
	/**
	 * Disable the clicks on the submit button.
	 * According to the boolean parameter it change the text of the button or not.
	 * 
	 * @param changeText Indicate whether the button text should be changed or not.
	 * */
	private void disableSubmit(boolean changeText)
	{
		submit.setEnabled(false);
		if(changeText)
		{
			submit.setText(R.string.buttonBusyFace);
		}
	}
		
	
//Activity implementation	
	
	/**
	 * Initialize all the references for the views of these layout.
	 * 
	 * Why the button is disabled at the beginning?
	 * Because we don't want the user to send empty statuses.
	 * 
	 * @see #disableSubmit(boolean)
	 * */
    @Override
    public void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_status);
        submit = (Button) findViewById(R.id.submit_BT);
        submit.setOnClickListener(this);
        editText = (EditText) findViewById(R.id.statusInput_ET);
        text = (TextView)findViewById(R.id.charsLeft_TV);
        editText.addTextChangedListener(this);
    }

    /**
     * Write the hint of the text view where the status will be written.
     * 
     * Why this is doing here?
     * Because this callback is called every time the activity gets focus (means visible and 
     * available to user) and so, the preferences may had changed (the value of {@code maxChars}).
     * If the {@code maxChars} value was changed we want to set the new value in the hint text,
     * saying how much characters the user can type.
     * */
   	@Override
	public void onResume() 
	{
   		super.onResume();
   		if(editText.getText().length() == 0)
   		{
   			disableSubmit(false);
   		}
   		editText.setHint(getResources().getString(R.string.statusHint1) 
        		+ app.SPACE_STRING + app.getMaxChars() + app.SPACE_STRING
        		+ getResources().getString(R.string.statusHint2));
	}
   	
   	/**
   	 * Set some menu items invisible (the ones that don't matter for this Activity).
   	 * 
   	 * Hide the status and the refresh menu item because there is none sense having them here.
   	 * */
   	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.shared_menu, menu);
		menu.getItem(2).setVisible(false);
		menu.getItem(3).setVisible(false);
		return true;
	}

   	/**
   	 * Delegate the behavior for each menu item when it's clicked.
   	 * 
   	 * When the item clicked is the timeline option, the action is to open the TimelineActivity.
	 * However, we added the flag {@code FLAG_ACTIVITY_REORDER_TO_FRONT} to the intent to avoid
	 * creating multiple activities of the same type. With this, if an activity is already in the
	 * background of this back stack, the desired activity will be brought to front instead of being
	 * created again.
	 * 
	 * If the item clicked is not a responsibility of this activity, the decision is given to the
	 * BaseActivity with the {@code super} call on the default closure.
	 * 
	 * @see BaseActivity#onOptionsItemSelected(MenuItem)
   	 * */
   	@Override
   	public boolean onOptionsItemSelected(MenuItem item) 
    {
		switch(item.getItemId())
		{
			case R.id.action_timeline:
				startActivity(new Intent(this, TimelineActivity.class)
					.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT));
				return true;
			default:
				return super.onOptionsItemSelected(item);
		}
	}	

	
//OnClickListener implementation
	

	/**
   	 * Send an intent to the service to publish the status.
   	 * 
   	 * Once the submit button is clicked, it is disabled and the intent is prepared to be sent to
   	 * the StatusUploadService.
   	 * A reference of this class is added to the {@code toNotifyList} of the General class to
   	 * guarantee that the service notify this class once the publish is done.
   	 * Also the private token is inserted into intent so this activity know when to "wake up" when
   	 * the service notifies him.
   	 * 
   	 * @see #disableSubmit(boolean)
   	 * */
	@Override
    public void onClick(View v) 
	{
    	disableSubmit(true);
    	if(uploadIntent == null)
		{
			uploadIntent = new Intent(getApplicationContext(), StatusUploadService.class);
		}
    	uploadIntent.putExtra(StatusUploadService.ARG_STATUS, editText.getText().toString());
    	uploadIntent.putExtra(StatusUploadService.ARG_TOKEN, onSuccessToken);
    	app.toNotifyList.add(this);
    	startService(uploadIntent);
    	uploadIntent.removeExtra(StatusUploadService.ARG_TOKEN);
    	uploadIntent.removeExtra(StatusUploadService.ARG_STATUS);
	}
	

//TextWatcher implementation
	
	/**
	 * Delegate the behavior when the status text is changed.
	 * Every time the message is changed, lot of things must be updated. The text view where the
	 * count of remain characters is shown, needs to be updated, increasing or decreasing the counter.
	 * The color of this counter values are also changed to red when the number of characters exceed
	 * the limit, and to black when the number of characters are below the limit. 
	 * The submit button should also be updated because when the length of the message is zero or 
	 * above the maximum number of characters allowed, this needed to be disabled so none invalid
	 * statuses are sent to the server.
	 * 
	 * Every time the status length is above the limit, a message is shown to user through a Toast
	 * object. 
	 * 
	 * @see #enableSubmit(boolean)
	 * @see #disableSubmit(boolean)
	 * */
	@Override
	public void onTextChanged(CharSequence arg0, int start, int before, int count)
	{	
		if(arg0.length() == 0)
		{
			text.setText(app.EMPTY_STRING);
			disableSubmit(false);
		}
		else
		{
			text.setText(String.valueOf(app.getMaxChars() - arg0.length()));
			enableSubmit(false);
		}
		if(arg0.length() > app.getMaxChars())
		{
			text.setTextColor(android.graphics.Color.RED);
			disableSubmit(false);
			Toast.makeText(this, R.string.maxCharsAccomplished, Toast.LENGTH_LONG).show();
		}
		else
		{
			text.setTextColor(android.graphics.Color.GREEN);
			enableSubmit(false);
		}	
	}

	/**
	 * Don't perform nothing but needs to be declared anyway because of this class implementation.
	 * */
	@Override
	public void afterTextChanged(Editable arg0) { /* DO NOTHING!*/ }
	
	/**
	 * Don't perform nothing but needs to be declared anyway because of this class implementation.
	 * */
	@Override
	public void beforeTextChanged(CharSequence arg0, int start, int count, int after) { /* DO NOTHING!*/ }

	
//IMyListener methods
	
	/**
	 * Perform some actions due to the service execution success.
	 * 
	 * Since the call to this method will be done by one thread from the service (not the UI thread)
	 * we need to delegate some actions to be taken in the UI thread.
	 * 
	 * So we use one Runnable type to define those actions and we send that Runnable to be ran on
	 * the UI thread, with the {@code runOnUiThread(onSuccessThread)} call. The Runnable type is 
	 * actually this StatusActivity because it implements the Runnable interface and the method
	 * {@code run()}. 
	 * 
	 * When the service successfully sent the status to the server, we need to clear the text from
	 * the user screen and enable the submit button.
	 * 
	 * @see #enableSubmit(boolean)
	 * */
	@Override
	public void onSuccess(Integer token)
	{
		if(token != onSuccessToken)
		{
			return;
		}
		runOnUiThread(this);
	}

	
//Runnable methods
	
	/**
	 * Delegate the actions to be taken on the UI thread when the service notifies this activity.
	 * 
	 * It simple clears the previous typed status from the screen and enables the submit button.
	 * */
	@Override
	public void run()
	{
		editText.setText(app.EMPTY_STRING);
		enableSubmit(true);
	}
	
}
